using UnityEngine;
using Tools;

namespace Core.Net
{
    public partial class NetManager
    {
        //Unity提供了一个Ping API，简化了Socket的Ping
        public int PingTime = 0;
        private bool isPinging = false; //是否正在Ping
        private bool startPing = false; //是否启动Ping
        private float pingStartTime;
        private const float maxPingWaitingTime = 2.0f; //最大Ping等待时长
        private readonly float PingRefreshTime = 5.5f; //一次Ping之间的间隔时间
        //当前Ping状况
        public static ePingState currentPingState = ePingState.OutOfTime;
        private float MaxWaitingPingTime = (RPCMsgManager.TIMEOUT * 2) / 1000f;

        public bool IsAutoReconnectNet = false; //是否开启自动重连

        public void RefreshNetTime(long serverTime)
        {
            _serverDateTime = serverTime.JavaTimeStampToDateTime();
        }

        private void NetPingCheck()
        {
            if (!startPing) return;
            if (!IsConnected)
            {
                UpdatePingState((int) (ePingState.OutOfTime));
            }
            else
            {
                //检查Ping  
                if (Time.unscaledTime - pingStartTime > PingRefreshTime && !isPinging)
                {
                    pingStartTime = Time.unscaledTime;
                    isPinging = true;
                    //启动Ping
                    var result = RPC.Heart.HeartBeatCall(NetHelper.GetEnvironmentTickCount(), (res, clientTick, serverTime) =>
                    {
                        if (!res.IsError)
                        {
                            // 时延= 来回 减去 发送接收所需时间帧
                            PingTime = Mathf.Clamp((int) (NetHelper.GetEnvironmentTickCount() - clientTick - Time.smoothDeltaTime * 1000 * 2), 0, int.MaxValue);
                            //更新服务器时间
                            RefreshNetTime(serverTime + PingTime);
                            _clientUpdateServerTimeTick = NetHelper.GetEnvironmentTickCount();
                            UpdatePingState(PingTime);
                        }
                        else
                        {
                            UpdatePingState((int) (ePingState.OutOfTime));
                        }
                    });
                    result.OnFinished.AddListener(res =>
                    {
                        isPinging = false;
                        if (res.errorType != RPCErrorType.None)
                        {
                            PingTime = (int) (ePingState.OutOfTime);
                        }
                    });
                }
                else if (isPinging) //当连接比较久，也能更新下状态
                {
                    var usedTime = Mathf.Clamp(Time.unscaledTime - pingStartTime - Time.smoothDeltaTime * 1000 * 2, 0, float.MaxValue);
                    if (usedTime > (int) currentPingState)
                    {
                        UpdatePingState(usedTime);
                    }
                    //如果Ping很久没更新，还是再Ping次
                    if (Time.unscaledTime - pingStartTime > MaxWaitingPingTime)
                    {
                        isPinging = false;
                    }
                }
            }
        }

        // 根据Ping时间更新Ping状态
        private void UpdatePingState(float pingTime)
        {
            //更新时延状态
            ePingState nextPingState;
            if (pingTime < (int) ePingState.GOOD)
            {
                nextPingState = ePingState.GOOD;
            }
            else if (pingTime < (int) ePingState.Normal)
            {
                nextPingState = ePingState.Normal;
            }
            else if (pingTime < (int) ePingState.Worse)
            {
                nextPingState = ePingState.Worse;
            }
            else
            {
                nextPingState = ePingState.OutOfTime;
                isPinging = false;
            }
            if (currentPingState != nextPingState)
            {
                currentPingState = nextPingState;
                OnPingStateChanged.Dispatch(currentPingState);
            }
        }

        //网络连接守护 
        private int connectCounter = 0;
        private const int connectGuardCheckRate = 50; //网络检查频率为50帧一次

        private void NetConnectGuard()
        {
            connectCounter++;
            if (connectCounter % connectGuardCheckRate == 0)
            {
                if (IsAutoReconnectNet && !IsConnected)
                {
                    if (socket != null && (!socket.IsAllSocketClosed()))
                    {
                    }
                    else
                    {
                        if (IsReturningToLogin)
                        {
                            
                        }
                        else
                        {
                            //开始重连 
                            OpenRetryRPCMessageBox(null);
                        }
                    }
                }
                connectCounter = 0;
            }
        }

        public void StartPing()
        {
            //开发模式不启动Ping 
#if DEVELOPMENT_BUILD
            startPing = true; //false;
#else
        startPing = true;
#endif
        }

        public void StopPing()
        {
            startPing = false;
        }

        /// <summary>
        /// 切换到网络睡眠模式
        /// </summary>
        public void SetConnectSleepMode(bool isSleep)
        {
            if (socket != null)
            {
                socket.ThreadSleepTime = isSleep ? 150 : CurrentSocketWaitTime;
            }
        }

        /// <summary>
        /// 设置网络通讯线程速度
        /// </summary>
        /// <param name="isFast"></param>
        public void SetConnectThreadSpeed(bool isFast)
        {
            if (socket == null) return;
            CurrentSocketWaitTime = isFast ? 20 : 500;
            socket.ThreadSleepTime = CurrentSocketWaitTime;
        }

        public void SetConnectThreadVeryFast(bool veryFast)
        {
            if (socket == null) return;
            socket.ThreadSleepTime = 1;
        }

        public NetworkType GetCurrentNetworkType()
        {
            switch (Application.internetReachability)
            {
                case NetworkReachability.NotReachable:
                    return NetworkType.None;
                case NetworkReachability.ReachableViaLocalAreaNetwork:
                    return NetworkType.WIFI;
                case NetworkReachability.ReachableViaCarrierDataNetwork:
                    return NetworkType.GPRS;
                default:
                    break;
            }
            return NetworkType.None;
        }

        /// <summary>
        /// Ping状态枚举，枚举值为对应Ping值状态的阈值
        /// </summary>
        public enum ePingState
        {
            /// <summary>
            /// 低延迟，一般是绿色
            /// </summary>
            GOOD = 50,
            /// <summary>
            /// 中等延迟，一般是黄色
            /// </summary>
            Normal = 150,
            /// <summary>
            /// 非常糟糕，一般是红色
            /// </summary>
            Worse = 300,
            /// <summary>
            /// 超时，一般是感叹号
            /// </summary>
            OutOfTime = (int) maxPingWaitingTime * 1000,
        }
    }
}